﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Diagnostics.Contracts;
using System.IO;

namespace ShredTheLog.Common
{
    public static class WebHelper
    {
        private static IObservable<WebResponse> GetResponseAsync(this WebRequest webRequest)
        {
            Contract.Requires(webRequest != null);
            Contract.Ensures(Contract.Result<IObservable<WebResponse>>() != null);

            var result = Observable.FromAsyncPattern<WebResponse>(webRequest.BeginGetResponse, webRequest.EndGetResponse)();
            Contract.Assume(result != null);
            return result;
        }

        private static IObservable<Stream> GetRequestStreamAsync(this WebRequest webRequest)
        {
            Contract.Requires(webRequest != null);
            Contract.Ensures(Contract.Result<IObservable<Stream>>() != null);

            var result = Observable.FromAsyncPattern<Stream>(webRequest.BeginGetRequestStream, webRequest.EndGetRequestStream)();
            Contract.Assume(result != null);
            return result;
        }

        public static IObservable<string> GetHttpRequest(Uri requestUri, Encoding responseEncoding)
        {
            Contract.Requires(requestUri != null);
            Contract.Requires(responseEncoding != null);
            Contract.Ensures(Contract.Result<IObservable<string>>() != null);

            var request = WebRequest.Create(requestUri);
            request.Method = "GET";
            var result =
                from response in request.GetResponseAsync()
                from responseString in response.GetResponseStream().ReadToEndAsync(responseEncoding)
                select responseString;
            Contract.Assume(result != null);
            return result;
        }

        public static IObservable<string> PostHttpRequest(Uri requestUri, string requestData, Encoding requestEncoding, Encoding responseEncoding, string contentType = null)
        {
            Contract.Requires(requestUri != null);
            Contract.Requires(requestData != null);
            Contract.Requires(requestEncoding != null);
            Contract.Requires(responseEncoding != null);
            Contract.Ensures(Contract.Result<IObservable<string>>() != null);

            var request = WebRequest.Create(requestUri);
            request.Method = "POST";
            request.ContentType = contentType;
            var result =
                from requestStream in request.GetRequestStreamAsync().Do(stream => stream.WriteAsync(requestData, requestEncoding))
                from response in request.GetResponseAsync()
                from responseString in response.GetResponseStream().ReadToEndAsync(responseEncoding)
                select responseString;
            Contract.Assume(result != null);
            return result;
        }
    }
}
